#include "CMatch.h"


void DestructionListener::SayGoodbye(b2Joint* joint)
{
    if (_match->_mouseJoint == joint)
    {
        _match->_mouseJoint = NULL;
    }
    else
    {
        _match->JointDestroyed(joint);
    }
}

CMatch::CMatch()
{
	initPhysics();
	_mouseJoint = NULL;
	b2BodyDef bodyDef;
    _groundBody = _world->CreateBody(&bodyDef);
	m_pSpriteTexture = NULL;
}

CMatch::~CMatch()
{
	
}


void CMatch::initPhysics()
{
	// Get window size and place the label upper. 
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();

	// Create a world
    b2Vec2 gravity;
    gravity.Set(0.0f, -30.0f);
    _world = new b2World(gravity);

    // Do we want to let bodies sleep?
    _world->SetAllowSleeping(true);

    _world->SetContinuousPhysics(true);

	// Debug Draw functions
	_debugDraw = new CDebugDrawGLES( P2M );
	_world->SetDebugDraw(_debugDraw);

	uint32 flags = 0;
	flags += b2Draw::e_shapeBit;
	_debugDraw->SetFlags(flags);

    // Define the ground body.
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0, 0); // bottom-left corner

    // Call the body factory which allocates memory for the ground body
    // from a pool and creates the ground box shape (also from a pool).
    // The body is also added to the world.
    b2Body* groundBody = _world->CreateBody(&groundBodyDef);

    // Define the ground box shape.
    b2EdgeShape groundBox;

    // bottom
    groundBox.Set(b2Vec2(0,0), b2Vec2(winSize.width/P2M, 0));
    groundBody->CreateFixture(&groundBox,0);

    // top
    groundBox.Set(b2Vec2(0,0), b2Vec2(0, winSize.height/P2M));
    groundBody->CreateFixture(&groundBox,0);

    // left
    groundBox.Set(b2Vec2(0, winSize.height/P2M), b2Vec2(winSize.width/P2M, winSize.height/P2M));
    groundBody->CreateFixture(&groundBox,0);

    // right
    groundBox.Set(b2Vec2(winSize.width/P2M, winSize.height/P2M), b2Vec2(winSize.width/P2M, 0));
    groundBody->CreateFixture(&groundBox,0);
}

void CMatch::draw()
{

	if (_mouseJoint)
    {
        b2Vec2 p1 = _mouseJoint->GetAnchorB();
        b2Vec2 p2 = _mouseJoint->GetTarget();

        b2Color c;
        c.Set(0.0f, 1.0f, 0.0f);
        _debugDraw->DrawPoint(p1, 4.0f, c);
        _debugDraw->DrawPoint(p2, 4.0f, c);

        c.Set(0.8f, 0.8f, 0.8f);
        _debugDraw->DrawSegment(p1, p2, c);
    }
	_world->DrawDebugData();

}

void CMatch::update(float dt)
{
	 int velocityIterations = 8;
    int positionIterations = 1;

    _world->Step(dt, velocityIterations, positionIterations);
}

void CMatch::addRect(CCNode* parent, CCPoint p)
{
	CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);    
    //We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
    //just randomly picking one of the images
	CCSpriteBatchNode * nodeParent = (CCSpriteBatchNode*) parent;
	m_pSpriteTexture = nodeParent->getTexture();

    int idx = (CCRANDOM_0_1() > .5 ? 0:1);
    int idy = (CCRANDOM_0_1() > .5 ? 0:1);
	CPhysicsSprite *sprite = new CPhysicsSprite();
    sprite->initWithTexture(m_pSpriteTexture, CCRectMake(32 * idx,32 * idy,32,32));
    sprite->autorelease();

    parent->addChild(sprite);
    
    sprite->setPosition( ccp( p.x, p.y) );
    
    // Define the dynamic body.
    //Set up a 1m squared box in the physics world
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(p.x/P2M, p.y/P2M);

    b2Body *body = _world->CreateBody(&bodyDef);
    
    // Define another box shape for our dynamic body.
    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
    
    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicBox;    
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    body->CreateFixture(&fixtureDef);

    sprite->setPhysicsBody(body);
	
}

bool CMatch::MouseDown(const b2Vec2& vec)
{
	b2Vec2 p = M2P*vec;
	_mouseWorld = p;
    
    if (_mouseJoint != NULL)
    {
        return false;
    }

    // Make a small box.
    b2AABB aabb;
    b2Vec2 d;
    d.Set(0.001f, 0.001f);
    aabb.lowerBound = p - d;
    aabb.upperBound = p + d;

    // Query the world for overlapping shapes.
    QueryCallback callback(p);
    _world->QueryAABB(&callback, aabb);

    if (callback.m_fixture)
    {
        b2Body* body = callback.m_fixture->GetBody();
        b2MouseJointDef md;
        md.bodyA = _groundBody;
        md.bodyB = body;
        md.target = p;
        md.maxForce = 1000.0f * body->GetMass();
        _mouseJoint = (b2MouseJoint*)_world->CreateJoint(&md);
        body->SetAwake(true);
        return true;
    }
    return false;
}

void CMatch::MouseUp(const b2Vec2& vec)
{
	if (_mouseJoint)
    {
        _world->DestroyJoint(_mouseJoint);
        _mouseJoint = NULL;
    }
}

void CMatch::MouseMove(const b2Vec2& vec)
{
	b2Vec2 p = M2P*vec;
	_mouseWorld = p;
    
    if(_mouseJoint)
    {
        _mouseJoint->SetTarget(p);
    }
}

void CMatch::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{

}

